package com.qmx.qmxapp.okhttp;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.qmx.qmxapp.R;
import com.qmx.qmxapp.bean.RegErrorMsg;
import com.qmx.qmxapp.utils.EStringUtils;
import com.qmx.qmxapp.utils.SysUtils;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


/**
 * Created by lzs on 2016/1/27.
 */
public class OkHttpHelper {

    private static final String TGA = "HTTP_REQUEST";

    private OkHttpClient okHttpClient;

    private static OkHttpHelper mInstance;

    private Gson mGson;

    private Handler mHandler;

    private Context mContext;

    private OkHttpHelper() {
        okHttpClient = new OkHttpClient();
        okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(30, TimeUnit.SECONDS);
        mGson = new Gson();
        mHandler = new Handler(Looper.getMainLooper());
    }

    //    static  {
    //        mInstance = new OkHttpHelper();
    //    }

    /**
     * 单例模式
     */
    public static OkHttpHelper getInstance() {
        if (mInstance == null) {
            synchronized (OkHttpHelper.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpHelper();
                }
            }
        }
        return mInstance;
    }
    //    public  OkHttpHelper getInstance() {
    //        return mInstance;
    //    }

    public void get(String url, boolean isProtect, Context context, BaseCallback callback) {
        mContext = context;
        Request request = null;
        if (isProtect == true) {
            request = buildRequestJsonProtect(url, getDefaultHeadParams(context), null, HttpMethodType.GET);
        } else {
            request = buildRequest(url, null, HttpMethodType.GET);
        }
        doRequest(request, callback);
    }

    /**
     * rsa加密解密
     *
     * @param url
     * @param isProtect
     * @param context
     * @param callback
     */
    public void getCrypt(String url, boolean isProtect, Context context, BaseCallback callback) {
        mContext = context;
        Request request = null;
        if (isProtect == true) {
            request = buildRequestJsonProtect(url, getDefaultHeadParams(context), null, HttpMethodType.GET);
        } else {
            request = buildRequest(url, null, HttpMethodType.GET);
        }
        doRequestGrypt(request, callback);
    }

    /*
    public void get(String url, BaseCallback callback){
        Request request =  buildRequest(url, null, HttpMethodType.GET);
        doRequest(request, callback);
    }
    */


    public void post(String url, boolean isProtect, String json, Context context, BaseCallback callback) {
        mContext = context;
        Request request = null;
        if (isProtect == true) {
            request = buildRequestJsonProtect(url, getDefaultHeadParams(context), json, HttpMethodType.POST);
        } else {
            request = buildRequestByJson(url, json, HttpMethodType.POST);
        }
        doRequest(request, callback);
    }

    //    public void post(String url, Map<String, String> params, Context context, BaseCallback callback) {
    //
    //        RequestBody formBody = new FormEncodingBuilder()
    //                .add("platform", "android")
    //                .add("name", "bug")
    //                .add("subject", "XXXXXXXXXXXXXXX")
    //                .build();
    //
    //        Request request = new Request.Builder()
    //                .url(url)
    //                .post(formBody)
    //                .build();
    //
    //        doRequest(request, callback);
    //    }


    public void post(String url, Map<String, String> params, BaseCallback callback) {
        Request request = buildRequest(url, params, HttpMethodType.POST);
        doRequest(request, callback);
    }

    public void post(String url, Map<String, Object> headParams, Map<String, String> params, BaseCallback callback) {
        Request request = buildRequestWithHeaderParams(url, headParams, params, HttpMethodType.POST);
        doRequest(request, callback);
    }
    /*
    public void post(String url, String json, BaseCallback callback){
        Request request =  buildRequestByJson(url, json, HttpMethodType.POST);

        doRequest(request, callback);
    }*/


    public void put(String url, boolean isProtect, String json, Context context, BaseCallback callback) {
        mContext = context;
        Request request = null;
        if (isProtect == true) {
            request = buildRequestJsonProtect(url, getDefaultHeadParams(context), json, HttpMethodType.PUT);
        } else {
            request = buildRequestByJson(url, json, HttpMethodType.PUT);
        }

        doRequest(request, callback);
    }

    /*
    public void put(String url, String json, BaseCallback callback) {
        Request request =  buildRequestByJson(url, json, HttpMethodType.PUT);

        doRequest(request, callback);
    }*/


    public void delect(String url, boolean isProtect, String json, Context context, BaseCallback callback) {
        mContext = context;
        Request request = null;
        if (isProtect == true) {
            request = buildRequestJsonProtect(url, getDefaultHeadParams(context), json, HttpMethodType.DELETE);
        } else {
            request = buildRequestByJson(url, json, HttpMethodType.DELETE);
        }

        doRequest(request, callback);
    }

    public void upload(String url, Context context, File file, String param, final OnProgressListener progressListener, BaseCallback callback) {
        mContext = context;
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        for (Map.Entry<String, Object> entry : getDefaultHeadParams(context).entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue().toString());
        }
        MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpg");

        RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM).
                addFormDataPart(param, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file)).build();

        ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, new ProgressListener() {
            @Override
            public void onProgress(final long currentBytes, final long contentLength, final boolean done) {
                final int progress = (int) ((float) currentBytes / (float) contentLength * 100);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        progressListener.onProgress(progress);
                    }
                });
            }
        });

        builder.post(progressRequestBody);

        Request request = builder.build();

        doRequest(request, callback);
    }

    //    /**
    //     * 下载安装apk
    //     * @param url
    //     * @param context
    //     */
    //    public void download(String url, Context context){
    //        mContext = context;
    //        final ProgressDialog dialog = new ProgressDialog(mContext);
    //        dialog.setCancelable(false);
    //        dialog.setMessage("正在下载...");
    //        dialog.show();
    //        Request request = new Request.Builder().url(url).build();
    //        okHttpClient.newCall(request).enqueue(new Callback() {
    //            @Override
    //            public void onFailure(Request request, IOException e) {
    //                Toast.makeText(mContext, mContext.getString(R.string.version_downloading_fail), Toast.LENGTH_SHORT).show();
    //                dialog.dismiss();
    //            }
    //
    //            @Override
    //            public void onResponse(Response response) throws IOException {
    //                String path = Environment.getExternalStorageDirectory() +"/" + Environment.DIRECTORY_DOWNLOADS;
    //                File downloadedFile = new File(path, "etao_app.apk");
    //                if (downloadedFile.exists()){
    //                    downloadedFile.delete();
    //                }
    //                BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile));
    //                sink.writeAll(response.body().source());
    //                sink.close();
    //                new SingleMediaScanner(mContext, downloadedFile);
    //                SysUtils.installApk(mContext, path);
    //                dialog.dismiss();
    //            }
    //        });
    //    }


    public void doRequest(Request request, final BaseCallback callback) {
        try {
            callback.onRequestBefore(request);
            okHttpClient.newCall(request).enqueue(new Callback() {

                @Override
                public void onFailure(Request request, IOException e) {
                    callback.onFailure(request, e);
                }

                @Override
                public void onResponse(Response response) throws IOException {
                    callback.onResponse(response);

                    if (response.isSuccessful()) {
                        String resultStr = response.body().string();
                        Log.d("okhttp", "=====>response_body:" + resultStr);
                        if (callback.mType == String.class) {
                            callbackSuccess(callback, response, resultStr);
                        } else {
                            try {
                                Object object = mGson.fromJson(resultStr, callback.mType);
                                callbackSuccess(callback, response, object);
                            } catch (JsonParseException e) {
                                callbackError(callback, response, response.code(), resultStr, e);
                            }
                        }
                    } else {
                        String resultStr = response.body().string();
                        Log.d("okhttp", "error=====>response_body:" + resultStr);
                        callbackError(callback, response, response.code(), resultStr, null);
                    }
                }
            });
        } catch (Exception e) {
            Log.e("HTTP_REQUEST", e.getMessage());
            //            Toast.makeText(mContext, "", Toast.LENGTH_SHORT).show();
//            HApplication.getInstance().finishAllActivity();
        } finally {

        }
    }

    /**
     * rsa加密解密
     *
     * @param request
     * @param callback
     */
    public void doRequestGrypt(Request request, final BaseCallback callback) {
        try {

            callback.onRequestBefore(request);
            okHttpClient.newCall(request).enqueue(new Callback() {

                @Override
                public void onFailure(Request request, IOException e) {
                    callback.onFailure(request, e);
                }

                @Override
                public void onResponse(Response response) throws IOException {
                    callback.onResponse(response);
                    if (response.isSuccessful()) {
                        String resultStr = response.body().string();
//                        Log.d("okhttp", "=====>response_body:" + resultStr);
//                        try {
//                            // 从文件中得到私钥
//                            InputStream inPrivate = HApplication.getInstance().getResources().getAssets().open("pkcs8_rsa_private_key.pem");
//                            PrivateKey privateKey = RSAUtils.loadPrivateKey(inPrivate);
//                            // 因为RSA加密后的内容经Base64再加密转换了一下，所以先Base64解密回来再给RSA解密
//                            byte[] decryptByte = RSAUtils.decryptData(Base64Utils.decode(resultStr), privateKey);
//                            resultStr = new String(decryptByte, "utf-8");
////                            Log.d("从文件中得到私钥", "mGoodsList====>response:" + response + " string:" + resultStr);
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                        }
                        if (callback.mType == String.class) {
                            callbackSuccess(callback, response, resultStr);
                        } else {
                            try {
                                Object object = mGson.fromJson(resultStr, callback.mType);
                                callbackSuccess(callback, response, object);
                            } catch (JsonParseException e) {
                                callbackError(callback, response, response.code(), resultStr, e);
                            }
                        }
                    } else {
                        String resultStr = response.body().string();
//                        Log.d("okhttpjia ", "error=====>response_body:" + resultStr);
                        callbackError(callback, response, response.code(), resultStr, null);
                    }
                }
            });
        } catch (Exception e) {
            Log.e("HTTP_REQUEST", e.getMessage());
            //            Toast.makeText(mContext, "", Toast.LENGTH_SHORT).show();
//            HApplication.getInstance().finishAllActivity();
        } finally {
        }
    }

    private Request buildRequestByJson(String url, String json, HttpMethodType methodType) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        String userAgen = mContext.getString(R.string.app_name)
                + "/" + SysUtils.getApplicationVersion(mContext)
                + " "
                + SysUtils.getProductModel()
                + "/" + SysUtils.getProductModelVersion();
        builder.addHeader("User-Agen", userAgen);

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            //            Log.i("POST", json);
            RequestBody body = RequestBody.create(JSON, json);
            //            Log.i(" HttpMethodType.POST", body.toString());
            builder.post(body);
        } else if (methodType == HttpMethodType.PUT) {
            RequestBody body = RequestBody.create(JSON, json);
            builder.put(body);
        }
        return builder.build();
    }


    private Request buildRequestJsonProtect(String url, Map<String, Object> headParams, String json, HttpMethodType methodType) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        Request.Builder builder = new Request.Builder();

        builder.url(url);

        if (null != headParams) {
            for (Map.Entry<String, Object> entry : headParams.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue().toString());
//                Log.d("TAG", entry.getKey() + ":" + entry.getValue().toString());
            }
        }
        String userAgen = mContext.getString(R.string.app_name)
                + "/" + SysUtils.getApplicationVersion(mContext)
                + " "
                + SysUtils.getProductModel()
                + "/" + SysUtils.getProductModelVersion();
        builder.addHeader("User-Agen", userAgen);

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            RequestBody body = RequestBody.create(JSON, json);
            //            Log.i(" HttpMethodType.POST", body.toString());
            builder.post(body);
        } else if (methodType == HttpMethodType.PUT) {
            RequestBody body;
            if (null == json) {
                body = RequestBody.create(JSON, "{}");
            } else {
                body = RequestBody.create(JSON, json);
            }
            builder.put(body);
        } else if (methodType == HttpMethodType.DELETE) {
            if (null == json) {
                builder.delete();
            } else {
                RequestBody body = RequestBody.create(JSON, json);
                builder.delete(body);
            }
        }

        return builder.build();
    }

    private Request buildRequest(String url, Map<String, String> params, HttpMethodType methodType) {
        return buildRequestWithHeaderParams(url, null, params, methodType);
    }

    private Request buildRequestWithHeaderParams(String url, Map<String, Object> headParams, Map<String, String> params, HttpMethodType methodType) {
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        if (null != headParams) {
            for (Map.Entry<String, Object> entry : headParams.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue().toString());
            }
        }

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            RequestBody body = buildFormData(params);
            //            Log.i(" HttpMethodType.POST", body.toString());
            builder.post(body);
        }

        return builder.build();
    }


    private RequestBody buildFormData(Map<String, String> params) {
        FormEncodingBuilder builder = new FormEncodingBuilder();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        return builder.build();
    }

    private void callbackSuccess(final BaseCallback callback, final Response response, final Object object) {
        //callback.onSuccess(response, object);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
//                Log.i("是否为---", response.toString() + "---" + object.toString());
                callback.onSuccess(response, object);
            }
        });
    }

    private void callbackError(final BaseCallback callback, final Response response, final int code, final String msg, final Exception e) {
        String resMsg = null;

        if (EStringUtils.isNotBlank(msg)) {
            try {
                RegErrorMsg responseErrorMsg = mGson.fromJson(msg, RegErrorMsg.class);
                resMsg = responseErrorMsg.getMessage();
            } catch (JsonParseException jsonException) {
                resMsg = "服务器忙,请稍后再试";
            }
        }

        final String finalResMsg = resMsg;

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (null != mContext && EStringUtils.isNotBlank(finalResMsg) && finalResMsg.equals("未授权")) {
                    Activity activity = (Activity) mContext;
                    if (null != activity) {
                        Log.d("okhttp", "=====>未授权");
                        //((EApplication) activity.getApplication()).finishAllActivity();
                        //                        Intent intent = new Intent(activity, IndexActivity.class);
                        //                        mContext.startActivity(intent);
                    }
                }
                callback.onError(response, code, finalResMsg, e);
            }
        });
    }

    private Map<String, Object> getDefaultHeadParams(Context context) {
        //        SharedPreferences share = context.getSharedPreferences(Constant.SP_ETAO_INFO, Context.MODE_PRIVATE);
        //        String token = share.getString("accessToken", "");

        long timestamp = System.currentTimeMillis() / 1000;

        Map<String, Object> headParams = new HashMap<String, Object>();
//        urlConnection.setRequestProperty("app-type", "Android");// 获取当前app类型
//        urlConnection.setRequestProperty("app-version", HaiGuoApp.version);// 获取当前apk的版本号
//        urlConnection.setRequestProperty("app-uuid", HaiGuoApp
//                .getInstance().getUuid());
//        urlConnection.setRequestProperty("timestamp",
//                String.valueOf(timestamp));
//        urlConnection.setRequestProperty("access-token",
//                Md5Util.md5(Constant.CLIENTID + Constant.CLIENTSECRET
//                        + PreferenceUtils.getPrefString(context,Constant.SP_KEY_UUId,"")
//                        + SysUtils.getApplicationVersion(context) + timestamp));

        headParams.put("app-type", "Android");
        headParams.put("app-version", SysUtils.getApplicationVersion(context));
//        headParams.put("app-uuid", PreferenceUtils.getPrefString(context, Constant.SP_KEY_UUId, ""));
//        headParams.put("timestamp", timestamp);
//        String accesstoken = Constant.CLIENTID + Constant.CLIENTSECRET
//                + PreferenceUtils.getPrefString(context, Constant.SP_KEY_UUId, "")
//                + SysUtils.getApplicationVersion(context) + timestamp;
//        headParams.put("access-token", accesstoken);
        return headParams;
    }

    enum HttpMethodType {
        GET,
        POST,
        PUT,
        DELETE
    }

    /**
     * 获取手机的UUID
     */
    @SuppressLint("MissingPermission")
    public String getMyUUID(Context context) {

        final TelephonyManager tm = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);

        final String tmDevice, tmSerial, androidId;

        tmDevice = "" + tm.getDeviceId();

        tmSerial = "" + tm.getSimSerialNumber();

        androidId = ""
                + android.provider.Settings.Secure.getString(
                context.getContentResolver(),
                android.provider.Settings.Secure.ANDROID_ID);

        UUID deviceUuid = new UUID(androidId.hashCode(),
                ((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());

        String uniqueId = deviceUuid.toString();

        // Log.d("debug", "uuid=" + uniqueId);

        return uniqueId;

    }
}
